<?php
define( 'ROLE_ADMIN', 1 );
define( 'ROLE_USER', 2 );
define( 'ROLE_ANONYMOUS', 3 );

class ForbiddenException extends Exception {
    protected $code = 403;
    protected $message = 'The request is denied!';

}

class NotFoundException extends Exception {
    protected $code = 404;
    protected $message = 'Handler not found!';

}

class Auth {

    const CLASS_TAG = 'Auth::';

    public static function GenTicket( $uname, $role, $seed ) {
        global $g_config;
        $timestamp = time();
        $plain = "$uname:$role:$timestamp:";
        return $plain . md5( base64_encode( $plain . $seed . ":" . $g_config[ "md5_salt" ] ) );
    }

    public static function CheckTicket( $ticket ) {
        Log::D( Auth::CLASS_TAG . 'CheckTicket.ticket : ' . $ticket );
        
        global $g_config;
        if ( !preg_match( "/^([^:]+:){3}[^:]+$/", $ticket ) ) {
            Log::E( Auth::CLASS_TAG . 'CheckTicket ticket format invaild.ticket:' . $ticket );
            return false;
        }
        list ( $uname, $role, $timestamp, $md5str ) = explode( ':', $ticket );
        $encryp = md5( base64_encode( "$uname:$role:$timestamp:" . Auth::GetSeed() . ":" . $g_config[ "md5_salt" ] ) );
        if ( $encryp === $md5str ) {
            return true;
        }
        Log::W( Auth::CLASS_TAG . 'CheckTicket ticket invaild.ticket : ' . $ticket );
        return false;
    }
    
    /* prevent ticket stolen */
    public static function GetSeed() {
        return $_SERVER[ "HTTP_USER_AGENT" ];
    }

    public static function CheckPermission( $required ) {
        Log::D( Auth::CLASS_TAG . 'CheckPermission.required : ' . $required );
        
        global $ticket;
        if ( $ticket && Auth::CheckTicket( $ticket ) ) {
            list ( $uname, $role, $timestamp, $md5str ) = explode( ':', $ticket );
        }
        else {
            $role = ROLE_ANONYMOUS;
        }
        
        if ( $role > $required ) { /* 1为最大角色，其它权限依数字越大，权限越小 */
            Log::W( Auth::CLASS_TAG . 'CheckPermission permission denied.' );
            throw new ForbiddenException( 'permission denied' );
        }
    }

}
?>